<script setup lang="ts">
import { onMounted, ref } from "vue";
import {
  reqUserAssignRole,
  reqUserBatchRemove,
  reqUserList,
  reqUserRoleList,
  reqUserSave,
  reqUserUpdate,
} from "@/api/acl/user";
import {
  RoleListResponseType,
  RoleListType,
  UserAssignRoleParamsType,
  UserListType,
  UserType,
} from "@/api/acl/user/type.ts";
import { ElMessage } from "element-plus";

// 定义表单数据
let userForm = ref<UserType>({
  createTime: "",
  phone: undefined,
  roleName: "",
  updateTime: "",
  id: "",
  username: "",
  name: "",
  password: "",
});

// 定义查询参数
let queryParam = ref({
  pageNo: 1,
  pageSize: 3,
  username: "",
});

// 定义总条数
const total = ref(30);

// 定义用户列表
let userList = ref<UserListType>([]);

// 抽屉的显示与隐藏
let drawer = ref(false);

// 抽屉的标题
let drawerTitle = ref("添加用户");

// 表单
let formRef = ref();

// 角色抽屉
let roleDrawer = ref(false);

// 角色分配列表的数据
let roleDrawerParams = ref({
  userId: "",
  username: "",
  assignRoles: [],
});

// 是否全选
let checkAllRoles = ref<boolean>(false);

// 是否半选
let isIndeterminate = ref<boolean>(true);

// 返回的所有的角色列表
let allRolesResp = ref<RoleListType>([]);

// 用户拥有的角色列表
let userRolesResp = ref<RoleListType>([]);

// 待删除的用户id列表
let idList = ref<number[]>([]);

// 分页大小改变时触发
const handleSizeChange = (val: number) => {
  queryParam.value.pageSize = val;
  getUserList();
};

// 当前页改变时触发
const handleCurrentChange = (val: number) => {
  queryParam.value.pageNo = val;
  getUserList();
};

// 获取用户列表
const getUserList = async () => {
  let result = await reqUserList(
    queryParam.value.pageNo,
    queryParam.value.pageSize,
    queryParam.value.username,
  );
  if (result.code === 200) {
    userList.value = result.data.records;
    total.value = result.data.total;
  }
};

// 新增用户
const addUser = async (user: UserType) => {
  let result = await reqUserSave(user);
  if (result.code === 200) {
    getUserList();
    ElMessage.success("添加成功");
  } else {
    ElMessage.error("添加失败");
  }
};

// 修改用户
const updateUser = async (user: UserType) => {
  let result = await reqUserUpdate(user);
  if (result.code === 200) {
    getUserList();
    ElMessage.success("修改成功");
  } else {
    ElMessage.error("修改失败");
  }
};

// 提交表单
const submit = async () => {
  // 如果表单验证不通过，直接返回
  await formRef.value.validate();

  if (userForm.value.id) {
    // 修改用户
    updateUser(userForm.value);
  } else {
    // 新增用户
    addUser(userForm.value);
  }
  // 关闭抽屉
  drawer.value = false;
  // 清空表单数据
  resetForm();
  // 清空表单验证信息
  clearValidatorMessage();
};

// 取消表单
const cancel = () => {
  // 关闭抽屉
  drawer.value = false;
  // 清空表单数据
  resetForm();
  // 清空表单验证信息
  clearValidatorMessage();
};

const resetForm = () => {
  Object.assign(userForm.value, {
    createTime: "",
    phone: undefined,
    roleName: "",
    updateTime: "",
    id: "",
    username: "",
    name: "",
    password: "",
  });
};

// 清空表单验证信息
const clearValidatorMessage = () => {
  formRef.value.clearValidate();
};

// 打开抽屉
const openDrawer = (row: UserType) => {
  drawer.value = true;
  // 将点击的行数据赋深拷贝给表单数据
  userForm.value = JSON.parse(JSON.stringify(row));
  if (row.id) {
    // 修改用户
    drawerTitle.value = "修改用户";
  } else {
    // 新增用户
    drawerTitle.value = "添加用户";
  }
};

// 自定义密码验证规则
const validatorPassword = (rule: any, value: any, callback: any) => {
  if (value) {
    if (value.length < 6 || value.length > 20) {
      callback(new Error("长度在 6 到 20 个字符"));
    } else {
      callback();
    }
  } else {
    callback(new Error("请输入密码"));
  }
};

// 打开角色抽屉
const openRoleDrawer = async (row: UserType) => {
  roleDrawer.value = true;
  Object.assign(roleDrawerParams.value, {
    userId: row.id,
    username: row.username,
    roleIdList: [],
  });
  let result: RoleListResponseType = await reqUserRoleList(row.id);
  if (result.code === 200) {
    userRolesResp.value = result.data.assignRoles;
    allRolesResp.value = result.data.allRolesList;
  }
};

// 全选的回调函数 val是全选的状态
const handleCheckAllChange = (val: boolean) => {
  userRolesResp.value = val ? allRolesResp.value : [];
  isIndeterminate.value = false; // 半选状态会影响全选状态，所以要先清除半选状态
};

// 单个选项的回调函数 value是选中的数组
const handleCheckedRolesChange = (value: string[]) => {
  const checkedCount = value.length;
  // 选中的数量等于所有的数量，全选
  checkAllRoles.value = checkedCount === allRolesResp.value.length;
  // 选中的数量大于0并且小于所有的数量，半选
  isIndeterminate.value =
    checkedCount > 0 && checkedCount < allRolesResp.value.length;
};

// 角色抽屉确定按钮
const rolesSubmit = async () => {
  //整理参数
  let data: UserAssignRoleParamsType = {
    userId: roleDrawerParams.value.userId,
    roleIdList: userRolesResp.value.map((item) => item.id as number),
  };
  // 发送请求 分配角色
  let result = await reqUserAssignRole(data);
  if (result.code === 200) {
    ElMessage.success("分配角色成功");
  } else {
    ElMessage.error("分配角色失败");
  }
  roleDrawer.value = false; //关闭抽屉
  getUserList(); // 重新获取列表
};

// 角色抽屉取消按钮
const rolesCancel = () => {
  roleDrawer.value = false;
};

// 删除用户 row是点击的行数据
const deleteUser = (row: UserType) => {
  // 整理数据
  let idList = [row.id as number];
  // 批量删除
  batchDeleteUser(idList);
  // 重新获取列表
  getUserList();
};

// 删除用户 批量删除
const batchDeleteUser = async (idList: number[]) => {
  let result = await reqUserBatchRemove(idList);
  if (result.code == 200) {
    ElMessage.success("删除成功");
  } else {
    ElMessage.error("删除失败");
  }
};

// 选中项发生变化时触发
// val是已经选中的项
const handleSelectionChange = (val: any) => {
  idList.value = val.map((item: UserType) => item.id as number);
};

// 批量删除
const deleteUsers = () => {
  batchDeleteUser(idList.value);
  getUserList();
};

// 重置搜索
const resetSearch = () => {
  queryParam.value.username = "";
  getUserList();
};

// 用户表单校验规则
const rules = {
  username: [
    { required: true, message: "请输入用户名", trigger: "blur" },
    { min: 5, max: 20, message: "长度在 5 到 20 个字符", trigger: "blur" },
  ],
  name: [
    { required: true, message: "请输入昵称", trigger: "blur" },
    { min: 5, max: 20, message: "长度在 5 到 20 个字符", trigger: "blur" },
  ],
  password: [
    //   validator 用于自定义验证规则
    { required: true, trigger: "blur", validator: validatorPassword },
  ],
};

// 页面加载时触发
onMounted(() => {
  getUserList();
});

defineOptions({
  name: "User",
});
</script>

<template>
  <!-- 顶部搜索框 -->
  <el-card class="search-card">
    <el-form inline class="form">
      <el-form-item label="用户名">
        <el-input
          placeholder="请输入用户名"
          v-model="queryParam.username"
        ></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="getUserList">搜索</el-button>
        <el-button @click="resetSearch">重置</el-button>
      </el-form-item>
    </el-form>
  </el-card>

  <!-- table展示 -->
  <el-card>
    <el-button type="primary" icon="plus" @click="openDrawer"
      >添加用户</el-button
    >
    <el-button
      type="danger"
      icon="delete"
      @click="deleteUsers"
      :disabled="!(idList.length > 0)"
      >批量删除</el-button
    >
    <el-table
      border
      :data="userList"
      class="table"
      @selection-change="handleSelectionChange"
    >
      <el-table-column
        align="center"
        type="selection"
        width="55"
      ></el-table-column>
      <el-table-column
        align="center"
        type="index"
        label="序号"
        width="55"
      ></el-table-column>
      <el-table-column
        align="center"
        label="用户名"
        prop="username"
      ></el-table-column>
      <el-table-column
        align="center"
        label="用户角色"
        prop="roleName"
      ></el-table-column>
      <el-table-column
        align="center"
        label="创建时间"
        prop="createTime"
      ></el-table-column>
      <el-table-column align="center" label="操作">
        <template #default="{ row }">
          <el-button type="primary" @click="openRoleDrawer(row)"
            >分配角色</el-button
          >
          <el-button type="info" @click="openDrawer(row)">编辑</el-button>
          <el-popconfirm
            width="250"
            :title="`确定删除用户${row.username}吗？`"
            confirmButtonText="确定"
            cancelButtonText="取消"
            icon="el-icon-question"
            @confirm="deleteUser(row)"
          >
            <template #reference>
              <el-button type="danger">删除</el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      v-model:current-page="queryParam.pageNo"
      v-model:page-size="queryParam.pageSize"
      :page-sizes="[1, 3, 5, 10]"
      :background="true"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      class="pagination"
    >
    </el-pagination>

    <!-- 抽屉 新增用户或者修改用户-->
    <el-drawer v-model="drawer" :title="drawerTitle">
      <el-form
        :model="userForm"
        label-width="68px"
        :rules="rules"
        ref="formRef"
      >
        <el-form-item label="用户名" prop="username">
          <el-input
            placeholder="请输入用户名称"
            v-model="userForm.username"
          ></el-input>
        </el-form-item>
        <el-form-item label="昵称" prop="name">
          <el-input v-model="userForm.name" placeholder="请输入昵称"></el-input>
        </el-form-item>
        <el-form-item label="密码" v-if="!userForm.id" prop="password">
          <el-input
            v-model="userForm.password"
            placeholder="请输入密码"
          ></el-input>
        </el-form-item>
        <!--
             如果使用form-item的话，label-width会强制左对齐，按钮就没有办法固定在右边
              所以使用div包裹，然后使用flex布局，让按钮固定在右边
             -->
        <div class="drawer-btn">
          <el-button type="primary" @click="submit">确定</el-button>
          <el-button @click="cancel">取消</el-button>
        </div>
      </el-form>
    </el-drawer>

    <el-drawer title="设置员工角色" v-model="roleDrawer">
      <template #default>
        <el-form v-model="roleDrawerParams">
          <el-form-item label="用户名">
            <el-input v-model="roleDrawerParams.username" disabled></el-input>
          </el-form-item>
          <el-form-item label="角色列表">
            <el-checkbox
              v-model="checkAllRoles"
              :indeterminate="isIndeterminate"
              @change="handleCheckAllChange"
              >全选</el-checkbox
            >
            <el-checkbox-group
              v-model="userRolesResp"
              @change="handleCheckedRolesChange"
            >
              <!--   label 就是最后收集的信息，下面的双花括号里面的页面显示的值           -->
              <el-checkbox
                v-for="(role, index) in allRolesResp"
                :key="index"
                :label="role"
              >
                {{ role.roleName }}
              </el-checkbox>
            </el-checkbox-group>
          </el-form-item>
        </el-form>
      </template>
      <template #footer>
        <el-button type="primary" @click="rolesSubmit">确 定</el-button>
        <el-button @click="rolesCancel">取 消</el-button>
      </template>
    </el-drawer>
  </el-card>
</template>

<style scoped lang="scss">
.box {
  width: 600px;
  height: 400px;
  background: #333333;
}

.form {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.search-card {
  height: 80px;
  margin-bottom: 10px;
}

.table {
  margin-top: 10px;
}

.pagination {
  margin-top: 10px;
  display: flex;
  justify-content: flex-end;
}

.drawer-btn {
  display: flex;
  justify-content: flex-end;
}
</style>
